package com.ylb.rent.controller;

import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.zxing.WriterException;
import com.ijpay.alipay.AliPayApi;
import com.sun.org.apache.xpath.internal.operations.Or;
import com.xiaoleilu.hutool.util.NumberUtil;
import com.xiaoleilu.hutool.util.ObjectUtil;
import com.xiaoleilu.hutool.util.StrUtil;
import com.ylb.rent.config.AliPayConfigBean;
import com.ylb.rent.config.PageConfig;
import com.ylb.rent.constant.OrderConstant;
import com.ylb.rent.constant.ResponseCode;
import com.ylb.rent.entity.Order;
import com.ylb.rent.entity.dto.RoomOrderDto;
import com.ylb.rent.entity.vo.OrderVo;
import com.ylb.rent.exception.BusinessException;
import com.ylb.rent.service.IOrderService;
import com.ylb.rent.util.AliPayUtil;
import com.ylb.rent.util.QrCodeUtil;
import com.ylb.rent.util.R;
import com.ylb.rent.util.TokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpRequest;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 * @AUTHOR:游李滨
 * @DATE:2023/7/5 10:31
 */
@RestController
@RequestMapping("/order")
@Slf4j()
public class OrderController {


    @Autowired
    IOrderService orderServiceImpl;


    @Autowired
    AliPayUtil aliPayUtil;

    @Autowired
    AliPayConfigBean aliPayConfigBean;

    @Autowired
    TokenUtil tokenUtil;
    /**
     *  新增订单，并且向rabbitmq发送限时消息
     * 返回结果： 无
     *
     *
     * */
    @PostMapping("/add")
    public String addOrder(@RequestBody RoomOrderDto orderDto, HttpServletRequest request){
        long userId = tokenUtil.getUserId();
        if(userId < 1){
            return R.errorJSONData(ResponseCode.NOT_AUTH,"请先登录");
        }



//        检查开始日期和结束日期
        if (ObjectUtil.isNull(orderDto.getFromDate()) || ObjectUtil.isNull(orderDto.getToDate())){
            return R.errorJSONData("请选择开始日期/结束日期");
        }
//        插入订单
        try{
            Order order = orderServiceImpl.insertOrder(orderDto);

            String orderNo = order.getOrderNo();
            if(StrUtil.hasEmpty(orderNo)){
                log.error("[添加订单] /order/add  错误,原因: 新增订单错误返回orderNo为空");
                return R.errorJSONData();
            }

            log.info("[添加订单] /order/add 生成OrderNo: [{}]",orderNo);
//        发送取消订单的消息
            orderServiceImpl.sendCancelMessage(orderNo);

//        讲orderNo:价格 存入session
            double totalAmount = order.getTotalAmount();
            request.getSession().setAttribute(orderNo,totalAmount);

            return R.successJSONData(orderNo);


        }catch (BusinessException e){
            return R.errorJSONData(e.getCode(),e.getMsg());
        }


    }
    /**
     *  前端传入一个订单编号，从session中查到总价，并生成支付二维码响应给前端
     * */
    @GetMapping("/qrCode")
    public void getQrCodeByOrderNo(String uuid,HttpSession session,HttpServletResponse response){
        double total = (double)session.getAttribute(uuid);
        if(StrUtil.isEmpty(uuid) || total == 0){
            return;
        }
        log.info("[添加订单] /order/qrCode 获取到orderNo={} , total={}",uuid,total);
        aliPayUtil.qrCode(uuid, String.valueOf(total),response);


    }

    @GetMapping("/list")
    public String getListByPage(Order order,PageConfig pageConfig){
        PageHelper.startPage(pageConfig);
        List<OrderVo> list = orderServiceImpl.list(order);

        return R.successJSONData(new PageInfo<>(list));
    }

    @PostMapping("/up")
    public String updateOrder(@RequestBody Order order){
        if(order.getId() < 1){
            return R.errorJSONData("订单id错误");
        }

        boolean b = orderServiceImpl.updateById(order);
        if(!b){
            return R.errorJSONData();
        }
        return R.successJSONData();
    }
    /**
     *  支付宝异步通知
     *  作用：根据OrderNo修改订单状态为成功
     *
     * */
    @PostMapping(value = "/notify")  // 注意这里必须是POST接口
    public void orderOk(HttpServletRequest request){
        System.out.println("notify ");
        try {
            // 获取支付宝POST过来反馈信息
            Map<String, String> params = AliPayApi.toMap(request);
            for (Map.Entry<String, String> entry :params.entrySet()) {
                System.out.println(entry.getKey() + " = " + entry.getValue());
            }
            boolean verifyResult = AlipaySignature.rsaCheckV1(params, aliPayConfigBean.getPublicKey(), "UTF-8", "RSA2");

            if (verifyResult) {
                String orderNo = params.get("out_trade_no");
                log.error("[支付成功] 获取到支付宝orderNo -- [{}]",orderNo);
                boolean b = orderServiceImpl.payOk(orderNo);

            } else {
                System.out.println("notify_url 验证失败");
                // TODO

            }
        } catch (AlipayApiException e) {
            e.printStackTrace();

        }
    }

    /**
     *  查询订单状态
     *
     * */
    @GetMapping("/status")
    public String getOrderById(String uuid){
        Order byId = orderServiceImpl.selectOrderByOrderNo(uuid);
        long status = byId.getStatus();
        return R.successJSONData(status);
    }



    /**
     * 返回值参数：
     *
     *                 System.out.println("交易名称: " + params.get("subject"));
     *                 System.out.println("交易状态: " + params.get("trade_status"));
     *                 System.out.println("支付宝交易凭证号: " + params.get("trade_no"));
     *                 System.out.println("商户订单号: " + params.get("out_trade_no"));
     *                 System.out.println("交易金额: " + params.get("total_amount"));
     *                 System.out.println("买家在支付宝唯一id: " + params.get("buyer_id"));
     *                 System.out.println("买家付款时间: " + params.get("gmt_payment"));
     *                 System.out.println("买家付款金额: " + params.get("buyer_pay_amount"));
     *                 // 更新订单为已支付(4)
     *
     * ————————————————
     * 返回结果:
     * charset = UTF-8
     * out_trade_no = 1676178576187199488
     * method = alipay.trade.page.pay.return
     * total_amount = 88.88
     * sign = Ep7aFE3O6FfqklZSC4/0ue3hMyduPII2ZDo4q8gJyuSgSc0pz0UtcS70o2mv9F40u9q1v2qe7QsDDkFLUPFtee5Jkh9ZERMhK6yYIr5SSjmLYUmRaIDX/y1aHJGCHvz0SQ8kIvC0qYlhGVQeBsmJUdeLTySXOKDyCw63B6XFrPAoRJjlpdx+6NOaSyF5dyhH9Dt3XoodDOEwYsjamFGS/BXTMJyGtThQQntqFt8uThzn7dNXVpLRPCvX62RCr7zAelBeOoRAkbrMihVAXT0JjP4CHimq268ejDH5b1rygBV3riBkDt1v2AJ/vkuem8ueTR/VEchsZUD6JZv7X2WLtg==
     * trade_no = 2023070422001487250500498221
     * auth_app_id = 9021000122699186
     * version = 1.0
     * app_id = 9021000122699186
     * sign_type = RSA2
     * seller_id = 2088721004587244
     * timestamp = 2023-07-04 18:39:33
     *
     *
     *
     * */
    @GetMapping(value = "/return")
    public void returnUrl(HttpServletRequest request) {
        System.out.println("return");
        try {
            // 获取支付宝GET过来反馈信息
            Map<String, String> map = AliPayApi.toMap(request);
//            for (Map.Entry<String, String> entry : map.entrySet()) {
//                System.out.println(entry.getKey() + " = " + entry.getValue());
//            }

            boolean verifyResult = AlipaySignature.rsaCheckV1(map, aliPayConfigBean.getPublicKey(), "UTF-8",
                    "RSA2");

            if (verifyResult) {
                // TODO 请在这里加上商户的业务逻辑程序代码
                System.out.println("return_url 验证成功");

                String orderNo = map.get("out_trade_no");
                boolean b = orderServiceImpl.payOk(orderNo);

                log.error("[order pay] -- {}",b);


            } else {

                // TODO

            }
        } catch (AlipayApiException e) {

            e.printStackTrace();

        }
    }

    @GetMapping("/qrCode/error")
    public void errorQrCode(HttpServletResponse response){
        try {
            log.error("[订单二维码出错了] 访问路径: /order/qrCode/error");
            QrCodeUtil.generateQrCode("系统出错了!请重新刷新页面或联系工作人员",response);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (WriterException e) {
            e.printStackTrace();
        }
    }

}
